﻿using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using AviFile;
using System.Drawing;

namespace AviDemo
{
    public class AviHandler
    {
        private int frameCount = 0;
        public VideoStream stream;

        public AviHandler()
        {
        }

        public int FrameCount
        {
            get
            {
                return frameCount;
            }
        }

        public List<String> ReadInfo(String source)
        {
            if (!File.Exists(source))
                throw new FileNotFoundException("Файл не найден");

            AviManager aviManager = new AviManager(source, true);
            stream = aviManager.GetVideoStream();
            List<String> list = new List<string>();
            frameCount = stream.CountFrames;
            list.Add("Ширина: " + stream.Width);
            list.Add("Высота: " + stream.Height);
            list.Add("Количество кадров: " + stream.CountFrames);
            list.Add("Frame Rate: " + stream.FrameRate);
            list.Add("Звук Wave:");
            try
            {
                AudioStream waveStream = aviManager.GetWaveStream();
                list.Add("Samples per Second: " + waveStream.CountSamplesPerSecond.ToString());
                list.Add("Bits per Sample: " + waveStream.CountBitsPerSample.ToString());
                list.Add("Channels: " + waveStream.CountChannels.ToString());
            }
            catch
            {
                list.Add(" None");
            }

            return list;
        }

        public int ExtractImages(string source, string dest)
        {
            if (Directory.Exists(dest))
            {
                if (!File.Exists(source))
                    throw new FileNotFoundException("Не найден файл AVI");

                AviManager aviManager = new AviManager(source, true);
                VideoStream stream = aviManager.GetVideoStream();
                stream.GetFrameOpen();
                int count = stream.CountFrames;
                for (int i = 0; i < stream.CountFrames; i++)
                    stream.ExportBitmap(i, Path.Combine(dest, i + ".bmp"));
                stream.GetFrameClose();
                aviManager.Close();
                return count;
            }
            else
                throw new FileNotFoundException("Папка назначения не найдена");
        }

        public void BuildNewFromImages(String dest, List<string> images, double rate, bool isCompressed)
        {
            List<Bitmap> bmpList = images.ConvertAll<Bitmap>(t => (Bitmap)Image.FromFile(t));
            if (bmpList.Count > 0)
            {
                AviManager aviManager = new AviManager(dest, false);
                VideoStream aviStream = aviManager.AddVideoStream(isCompressed, rate, bmpList[0]);
                for (int i = 1; i < bmpList.Count; i++)
                    aviStream.AddFrame(bmpList[i]);
                aviManager.Close();
            }
            bmpList.ForEach(t => t.Dispose());
        }

        public void AppendImageToExist(string source, string dest, List<string> images)
        {
            if (!File.Exists(source))
                throw new FileNotFoundException("Не найден файл AVI");

            List<Bitmap> bmpList = images.ConvertAll<Bitmap>(t => (Bitmap)Image.FromFile(t));
            AviManager aviManager = new AviManager(source, true);
            VideoStream aviStream = aviManager.GetVideoStream();

      
            VideoStream newStream;
            AviManager newManager = aviStream.DecompressToNewFile(dest, true, out newStream);
            aviStream = newStream; 

            for (int i = 1; i < bmpList.Count; i++)
                aviStream.AddFrame(bmpList[i]);
            bmpList.ForEach(t => t.Dispose());
         
            aviManager.Close();
   
            newManager.Close();
        }

        public void CopyFile(String source, String dest, bool isCompressed)
        {
            if (!File.Exists(source))
                throw new FileNotFoundException("Source media file is not found");


            AviManager aviManager = new AviManager(source, true);
            VideoStream aviStream = aviManager.GetVideoStream();
        
            VideoStream newStream;
            AviManager newManager = aviStream.DecompressToNewFile(dest, isCompressed, out newStream);
    
            aviManager.Close();

            newManager.Close();
        }

        public Bitmap GetFrame(string source, int position)
        {
            if (!File.Exists(source))
                throw new FileNotFoundException("Source media file is not found");
            AviManager aviManager = null;
            VideoStream aviStream = null;
            Bitmap bmp = null;
            try
            {
                aviManager = new AviManager(source, true);
                aviStream = aviManager.GetVideoStream();
                aviStream.GetFrameOpen();
                if (position > -1 && aviStream.CountFrames > position)
                    bmp = aviStream.GetBitmap(position);
                else
                    throw new IndexOutOfRangeException("Frame position is invalid");
            }
            finally
            {
                aviStream.GetFrameClose();
                aviManager.Close();
            }
            return bmp;
        }

        public void ExtractAudio(string source, string dest)
        {
            using (AviManager aviManager = new AviManager(source, true))
            {
                AudioStream audioStream = aviManager.GetWaveStream();
                audioStream.ExportStream(dest);
            }
        }

        public void AddSound(string source, string waveSource, int insertPosition)
        {
            using (AviManager aviManager = new AviManager(source, true))
            {
                int countFrames = aviManager.GetVideoStream().CountFrames;
                if (insertPosition > -1 && countFrames > insertPosition)
                    aviManager.AddAudioStream(waveSource, insertPosition);
                else
                    throw new IndexOutOfRangeException("Frame " + insertPosition + " does not exists");
            }
        }

        public void ExtractVideo(string source, string dest)
        {
            if (!File.Exists(source))
                throw new FileNotFoundException("Source media file is not found");
            using (AviManager aviManager = new AviManager(source, true))
            {
                VideoStream videoStream = aviManager.GetVideoStream();
                videoStream.ExportStream(dest);
            }
        }
    }
}
